home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Disc to the Future 2
/
Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin
/
MAC
/
MPW_TOOL
/
TOOLS
/
TOOLS_WI
/
ICON_8
/
ICONX_FO
/
OSET.C
< prev
next >
Wrap
Text File
|
1990-03-02
|
8KB
|
297 lines
/*
* File: oset.c
* Contents: compl, diff, inter, unions
*/
#include "::h:config.h"
#include "::h:rt.h"
#include "rproto.h"
#ifdef PreProcess
/* include(../M4/ops.m4) /* */
/* */
#endif /* PreProcess */
/*
* ~x - complement cset x.
*/
OpDcl(compl,1,"~")
{
register int i;
union block *bp;
int *cs, csbuf[CsetSize];
if (blkreq((word)sizeof(struct b_cset)) == Error)
RunErr(0, NULL);
/*
* Arg1 must be a cset.
*/
if (cvcset(&Arg1, &cs, csbuf) == CvtFail)
RunErr(104, &Arg1);
/*
* Allocate a new cset and then copy each cset word from Arg1
* into the new cset words, complementing each bit.
*/
bp = (union block *)alccset();
for (i = 0; i < CsetSize; i++)
bp->cset.bits[i] = ~cs[i];
Arg0.dword = D_Cset;
BlkLoc(Arg0) = bp;
Return;
}
/*
* x -- y - difference of csets x and y or of sets x and y.
*/
OpDcl(diff,2,"--")
{
register word i;
word slotnum;
register union block *srcp, *tstp, *dstp, **hook;
int *cs1, *cs2, csbuf1[CsetSize], csbuf2[CsetSize], res;
struct b_slots *seg;
struct b_selem *ep;
if (Qual(Arg1) || Qual(Arg2))
goto skipsets;
if (Arg1.dword == D_Set && Arg2.dword != D_Set)
RunErr(119, &Arg2);
if (Arg2.dword == D_Set && Arg1.dword != D_Set)
RunErr(119, &Arg1);
if (Arg1.dword == D_Set && Arg2.dword == D_Set) {
/*
* Both Arg1 and Arg2 are sets - do set difference. Make a new set
* based on the size of Arg1.
*/
dstp = hmake(T_Set, (word)0, BlkLoc(Arg1)->set.size);
if (dstp == NULL)
RunErr(0, NULL);
/*
* For each element in set Arg1 if it is not in set Arg2
* copy it directly into the result set.
*/
srcp = BlkLoc(Arg1);
tstp = BlkLoc(Arg2);
for (i = 0; i < HSegs && (seg = srcp->set.hdir[i]) != NULL; i++)
for (slotnum = segsize[i] - 1; slotnum >= 0; slotnum--) {
ep = (struct b_selem *)seg->hslots[slotnum];
while (ep != NULL) {
memb(tstp, &ep->setmem, ep->hashnum, &res);
if (res == 0) {
hook = memb(dstp, &ep->setmem, ep->hashnum, &res);
addmem(&dstp->set, alcselem(&ep->setmem, ep->hashnum), hook);
}
ep = (struct b_selem *)ep->clink;
}
}
Arg0.dword = D_Set;
BlkLoc(Arg0) = dstp;
if (TooSparse(dstp))
hshrink(&Arg0);
}
else {
skipsets:
if (blkreq((word)sizeof(struct b_cset)) == Error)
RunErr(0, NULL);
/*
* Arg1 and Arg2 must be csets.
*/
if (cvcset(&Arg1, &cs1, csbuf1) == CvtFail)
RunErr(120, &Arg1);
if (cvcset(&Arg2, &cs2, csbuf2) == CvtFail)
RunErr(120, &Arg2);
/*
* Allocate a new cset and in each word of it, compute the value
* of the bitwise difference of the corresponding words in the
* Arg1 and Arg2 csets.
*/
dstp = (union block *)alccset();
for (i = 0; i < CsetSize; i++) {
dstp->cset.bits[i] = cs1[i] & ~cs2[i];
}
Arg0.dword = D_Cset;
BlkLoc(Arg0) = dstp;
}
Return;
}
/*
* x ** y - intersection of csets x and y or of sets x and y.
*/
OpDcl(inter,2,"**")
{
register word i;
word slotnum;
register union block *srcp, *tstp, *dstp, **hook;
int *cs1, *cs2, csbuf1[CsetSize], csbuf2[CsetSize], res;
struct b_slots *seg;
struct b_selem *ep;
if (Qual(Arg1) || Qual(Arg2))
goto skipsets;
if (Arg1.dword == D_Set && Arg2.dword != D_Set)
RunErr(119, &Arg2);
if (Arg2.dword == D_Set && Arg1.dword != D_Set)
RunErr(119, &Arg1);
if (Arg1.dword == D_Set && Arg2.dword == D_Set) {
/*
* Both Arg1 and Arg2 are sets - do set intersection.
* Make a new set the size of the smaller argument set.
*/
dstp = hmake(T_Set, (word)0,
Min(BlkLoc(Arg1)->set.size, BlkLoc(Arg2)->set.size));
if (dstp == NULL)
RunErr(0, NULL);
/*
* Using the smaller of the two sets as the source
* copy directly into the result each of its elements
* that are also members of the other set.
*/
if (BlkLoc(Arg1)->set.size <= BlkLoc(Arg2)->set.size) {
srcp = BlkLoc(Arg1);
tstp = BlkLoc(Arg2);
}
else {
srcp = BlkLoc(Arg2);
tstp = BlkLoc(Arg1);
}
for (i = 0; i < HSegs && (seg = srcp->set.hdir[i]) != NULL; i++)
for (slotnum = segsize[i] - 1; slotnum >= 0; slotnum--) {
ep = (struct b_selem *)seg->hslots[slotnum];
while (ep != NULL) {
memb(tstp, &ep->setmem, ep->hashnum, &res);
if (res != 0) {
hook = memb(dstp, &ep->setmem, ep->hashnum, &res);
addmem(&dstp->set, alcselem(&ep->setmem, ep->hashnum), hook);
}
ep = (struct b_selem *)ep->clink;
}
}
Arg0.dword = D_Set;
BlkLoc(Arg0) = dstp;
if (TooSparse(dstp))
hshrink(&Arg0);
}
else {
skipsets:
if (blkreq((word)sizeof(struct b_cset)) == Error)
RunErr(0, NULL);
/*
* Arg1 and Arg2 must be csets.
*/
if (cvcset(&Arg1, &cs1, csbuf1) == CvtFail)
RunErr(120, &Arg1);
if (cvcset(&Arg2, &cs2, csbuf2) == CvtFail)
RunErr(120, &Arg2);
/*
* Allocate a new cset and in each word of it, compute the value
* of the bitwise intersection of the corresponding words in the
* Arg1 and Arg2 csets.
*/
dstp = (union block *)alccset();
for (i = 0; i < CsetSize; i++) {
dstp->cset.bits[i] = cs1[i] & cs2[i];
}
Arg0.dword = D_Cset;
BlkLoc(Arg0) = dstp;
}
Return;
}
/*
* x ++ y - union of csets x and y or of sets x and y.
*/
OpDcl(unions,2,"++")
{
register word i;
word slotnum;
register union block *srcp, *tstp, *dstp, **hook;
int *cs1, *cs2, csbuf1[CsetSize], csbuf2[CsetSize], res;
struct b_slots *seg;
struct b_selem *ep;
dptr srcd, tstd;
if (Qual(Arg1) || Qual(Arg2))
goto skipsets;
if (Arg1.dword == D_Set && Arg2.dword != D_Set)
RunErr(119, &Arg2);
if (Arg2.dword == D_Set && Arg1.dword != D_Set)
RunErr(119, &Arg1);
if (Arg1.dword == D_Set && Arg2.dword == D_Set) {
/*
* Both Arg1 and Arg2 are sets - do set union. Copy the larger set
* and ensure there's room for *Arg1 + *Arg2 elements.
*/
if (BlkLoc(Arg1)->set.size >= BlkLoc(Arg2)->set.size) {
srcd = &Arg1;
tstd = &Arg2;
}
else {
srcd = &Arg2;
tstd = &Arg1;
}
if (cpset(srcd, &Arg0, BlkLoc(Arg1)->set.size + BlkLoc(Arg2)->set.size)
== Error)
RunErr(0, NULL);
/*
* Copy each element from the smaller set into the result set,
* if it is not already there.
*/
srcp = BlkLoc(*srcd);
tstp = BlkLoc(*tstd);
dstp = BlkLoc(Arg0);
for (i = 0; i < HSegs && (seg = tstp->set.hdir[i]) != NULL; i++)
for (slotnum = segsize[i] - 1; slotnum >= 0; slotnum--) {
ep = (struct b_selem *)seg->hslots[slotnum];
while (ep != NULL) {
hook = memb(dstp, &ep->setmem, ep->hashnum, &res);
if (res == 0)
addmem(&dstp->set, alcselem(&ep->setmem, ep->hashnum), hook);
ep = (struct b_selem *)ep->clink;
}
}
if (TooCrowded(dstp)) /* if the union got too big, enlarge */
hgrow(&Arg0);
}
else {
skipsets:
if (blkreq((word)sizeof(struct b_cset)) == Error)
RunErr(0, NULL);
/*
* Arg1 and Arg2 must be csets.
*/
if (cvcset(&Arg1, &cs1, csbuf1) == CvtFail)
RunErr(120, &Arg1);
if (cvcset(&Arg2, &cs2, csbuf2) == CvtFail)
RunErr(120, &Arg2);
/*
* Allocate a new cset and in each word of it, compute the value
* of the bitwise union of the corresponding words in the
* Arg1 and Arg2 csets.
*/
dstp = (union block *)alccset();
for (i = 0; i < CsetSize; i++) {
dstp->cset.bits[i] = cs1[i] | cs2[i];
}
Arg0.dword = D_Cset;
BlkLoc(Arg0) = dstp;
}
Return;
}